import org.junit.jupiter.api.Test;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;

/**
 * OffsetTime类用于表示偏离UTC的时间，由time和offset两个变量表示。其中time是LocalTime类的对象，表示时间，
 * offset是ZoneOffset类的对象，用于表示time对象相对于UTC时间的偏移量。
 * ”+08:00“表示比UTC时间快8小时，”-08:00“表示比UTC时间慢8小时。
 */
public class OffsetTimeDemo {

    /**
     * MAX：offsetTime对象能表示的最大值。
     * MIN：offsetTime对象能表示的最小值。
     */
    @Test
    public void test01(){
        System.out.println(OffsetTime.MAX); // 输出 23:59:59.999999999-18:00
        System.out.println(OffsetTime.MIN); // 输出 00:00+18:00
    }
}

class OffsetTimeDemo01 {

    /**
     * from(TemporalAccessor temporal)
     * 作用：从其它具有偏移量概念的时间对象获取 offsetTime 对象。
     */
    @Test
    public void test01(){
        ZonedDateTime zonedDateTime01 = ZonedDateTime.parse("2023-01-01T08:00:00+08:00[Asia/Shanghai]");
        OffsetTime offsetTime01 = OffsetTime.from(zonedDateTime01);
        System.out.println(offsetTime01); // 输出 08:00+08:00
    }

    /**
     * now()
     * 作用：从操作系统获取 offsetTime 对象。
     *
     * now(ZoneId zone)
     * 作用：获取指定时区此刻的时间。
     *
     * now(Clock clock)
     * 作用：从 clock 对象获取 offsetTime 对象。clock 对象有时区的概念，
     *      获取的是 clock 对象指定时区的时间。
     */
    @Test
    public void test02(){
        OffsetTime offsetTime01 = OffsetTime.now();
        System.out.println(offsetTime01); // 输出 10:25:57.680+08:00 （系统时间：10:25)

        ZoneId zoneId01 = ZoneId.of("America/Los_Angeles");
        OffsetTime offsetTime02 = OffsetTime.now(zoneId01);
        System.out.println(offsetTime02); // 输出 19:25:57.682-07:00 （系统时间：10:25)

        Instant instant01 = Instant.parse("2023-04-01T10:00:00Z");
        Clock fixedClock01 = Clock.fixed(instant01, zoneId01);
        OffsetTime offsetTime03 = OffsetTime.now(fixedClock01);
        System.out.println(offsetTime03); // 输出 03:00-07:00
    }

    /**
     * of(int hour, int minute, int second, int nanoOfSecond, ZoneOffset offset)
     * of(LocalTime time, ZoneOffset offset)
     * ofInstant(Instant instant, ZoneId zone)
     * 作用：给定时分秒以及偏移量数据创建 offsetTime 对象。
     */
    @Test
    public void test03(){
        ZoneOffset zoneOffset01 = ZoneOffset.of("+07:00");
        OffsetTime offsetTime01 = OffsetTime.of(12, 30, 45, 100, zoneOffset01);
        System.out.println(offsetTime01); // 输出 12:30:45.000000100+07:00

        LocalTime time01 = LocalTime.parse("12:30:45.000000100");
        OffsetTime offsetTime02 = OffsetTime.of(time01, zoneOffset01);
        System.out.println(offsetTime02); // 输出 12:30:45.000000100+07:00

        Instant instant01 = Instant.parse("2023-01-01T12:30:45.000000100Z");
        OffsetTime offsetTime03 = OffsetTime.ofInstant(instant01, zoneOffset01);
        System.out.println(offsetTime03); // 输出 19:30:45.000000100+07:00
    }

    /**
     * parse(CharSequence text)
     * parse(CharSequence text, DateTimeFormatter formatter)
     * 作用：将字符串解析成 offsetTime 对象，默认格式 HH:mm:ssxxx，
     *      xxx 表示偏移量，formatter 用来指定字符串格式。
     */
    @Test
    public void test04(){
        OffsetTime offsetTime01 = OffsetTime.parse("12:30:45+08:00");
        System.out.println(offsetTime01); // 输出 12:30:45+08:00

        DateTimeFormatter df01 = DateTimeFormatter.ofPattern("HH时mm分ss秒 偏移量xxx");
        OffsetTime offsetTime02 = OffsetTime.parse("12时30分45秒 偏移量+08:00", df01);
        System.out.println(offsetTime02); // 输出 12:30:45+08:00
    }
}

class OffsetTimeDemo02{

    /**
     * atDate(LocalDate date)
     * 作用：补充年月日数据生成 offsetDateTime 对象。
     */
    @Test
    public void test01(){
        OffsetTime offsetTime01 = OffsetTime.parse("12:30:45+08:00");
        LocalDate date01 = LocalDate.parse("2023-01-01");
        OffsetDateTime offsetDateTime01 = offsetTime01.atDate(date01);
        System.out.println(offsetDateTime01); // 输出 2023-01-01T12:30:45+08:00
    }

    /**
     * format(DateTimeFormatter formatter)
     * 作用：格式化输出 offsetTime 对象。
     */
    @Test
    public void test02(){
        OffsetTime offsetTime01 = OffsetTime.parse("12:30:45+08:00");
        DateTimeFormatter df01 = DateTimeFormatter.ofPattern("HH小时mm分钟ss秒 偏移量：xxx");
        String offsetTimeStr = offsetTime01.format(df01);
        System.out.println(offsetTimeStr); // 输出 12小时30分钟45秒 偏移量：+08:00
    }

    /**
     * toLocalTime()
     * 作用：获取不带偏移量的 localTime 对象。
     */
    @Test
    public void test03(){
        OffsetTime offsetTime01 = OffsetTime.parse("12:30:45+08:00"); // UTC时间 04:30:45
        LocalTime localTime01 = offsetTime01.toLocalTime();
        System.out.println(localTime01); // 输出 12:30:45
    }

    /**
     * truncatedTo(TemporalUnit unit)
     * 作用：根据时间单位截取 offsetTime 对象。
     */
    @Test
    public void test04(){
        OffsetTime offsetTime01 = OffsetTime.parse("12:30:45+08:00"); // UTC时间 04:30:45
        OffsetTime offsetTime02 = offsetTime01.truncatedTo(ChronoUnit.MINUTES);
        OffsetTime offsetTime03 = offsetTime01.truncatedTo(ChronoUnit.HOURS);
        System.out.println(offsetTime01); // 输出 12:30:45+08:00
        System.out.println(offsetTime02); // 输出 12:30+08:00
        System.out.println(offsetTime03); // 输出 12:00+08:00
    }

    /**
     * until(Temporal endExclusive, TemporalUnit unit)
     * 作用：根据指定的时间单位计算两个 offsetTime 对象的差值。
     */
    @Test
    public void test05(){
        OffsetTime offsetTime01 = OffsetTime.parse("08:00:00+08:00"); // UTC时间 00:00:00
        OffsetTime offsetTime02 = OffsetTime.parse("09:00:00+08:00"); // UTC时间 01:00:00
        OffsetTime offsetTime03 = OffsetTime.parse("07:00:00+07:00"); // UTC时间 00:00:00

        System.out.println(offsetTime01.until(offsetTime02, ChronoUnit.HOURS)); // 输出 1
        System.out.println(offsetTime01.until(offsetTime03, ChronoUnit.HOURS)); // 输出 0
    }

    /**
     * withOffsetSameInstant(ZoneOffset offset)
     * 作用：通过调整偏移量来调整 offsetTime 对象，
     *      但不管如何调整，转换成的 UTC 时间不变。
     *
     * withOffsetSameLocal(ZoneOffset offset)
     * 作用：时间不变，仅改变偏移量。
     */
    @Test
    public void test06(){
        OffsetTime offsetTime01 = OffsetTime.parse("08:00+08:00"); // UTC时间 00:00
        ZoneOffset zoneOffset01 = ZoneOffset.of("+07:00");
        ZoneOffset zoneOffset02 = ZoneOffset.of("-08:00");
        System.out.println(offsetTime01.withOffsetSameInstant(zoneOffset01)); // 输出 07:00+07:00 （UTC时间 00:00）
        System.out.println(offsetTime01.withOffsetSameInstant(zoneOffset02)); // 输出 16:00-08:00 （UTC时间 00:00）

        OffsetTime offsetTime02 =OffsetTime.parse("08:00+08:00"); // UTC时间 00:00
        System.out.println(offsetTime02.withOffsetSameLocal(zoneOffset01)); // 输出 08:00+07:00 （UTC时间 01:00）
        System.out.println(offsetTime02.withOffsetSameLocal(zoneOffset02)); // 输出 08:00-08:00 （UTC时间 16:00）
    }
}